#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

void judge2(int &x) {  // 左值引用
    cout << "(left value - 2) ";
    return ;
}

void judge2(int &&x) {  // 右值引用
    cout << "(right value - 2) ";
    return ;
}

void judge(int &x) {  // 左值引用
    judge2(x);
    cout << "left value" << endl;
    return ;
}

void judge(int &&x) {  // 右值引用
//    judge2(x); // 左值右值是有作用域的
//    judge2(move(x)); // move()可以直接将值转为右值
    judge2(forward<int &&>(x)); // 将值得类型转换成我们想要的类型
    cout << "right value" << endl;
    return ;
}

#define TEST(a) { \
    cout << "judge " << #a << " : "; \
    judge(a); \
}

int main() {
    int n = 123;
    TEST(n); // left value
    TEST(n + 1); // right value
    TEST(n++); // right value
    TEST(++n); // left value
    TEST(1 + 2); // right value
    TEST(n += 2); // left value

    return 0;
}

ENDS(test1)


BEGINS(test2)

class Point;

void judge(Point &x) {  // 左值引用
    cout << "left value" << endl;
    return;
}

void judge(Point &&x) {  // 右值引用
    cout << "right value" << endl;
    return;
}

class Point {
public:
    Point(int x = 0, int y = 0) : __x(x), __y(y) {}
    int x() { return __x; }
    int y() { return __y; }
    Point &operator+=(int d) {
        __x += d;
        __y += d;
        return *this;
    }
    Point operator+(int d) {
        Point p(__x + d, __y + d);
        return p;
    }
private:
    int __x, __y;
};

#define TEST(a) { \
    cout << "judge " << #a << " : "; \
    judge(a); \
}

int main() {
    Point p(3, 4);
    TEST(p);
    TEST(p += 1); // 因为 p+=1 是一个左值，所以+=运算符应该返回引用
    TEST(p + 1); // 因为 p+1 是一个右值，所以+运算符返回是一个临时的值
    return 0;
}

ENDS(test2)

// 移动构造
/*
 * 拷贝行为：
 * 1.构造
 *   1.1 左值
 *   1.2 右值
 * 2.赋值
 *   2.1 左值
 *   2.2 右值
 */
BEGINS(test3)

template<typename T>
class Array {
public:
    Array(int n = 5) : __size(n), data(new T[n]) {
        cout << this << " default constructor" << endl;
    }
    // deep copy O(n)的操作
    Array(const Array<T> &a) : __size(a.__size), data(new T[__size]) {
        for (int i = 0; i < __size; i++) {
            data[i] = a[i];
        }
        cout << this << " deep copy constructor" << endl;
    }
    // move constructor O(1)的操作
    Array(Array &&a) : __size(a.__size), data(a.data) {
        a.data = nullptr;
        a.__size = 0;
        cout << this << "move constructor" << endl;
    }
    T &operator[](int ind) { return data[ind]; }
    const T &operator[](int ind) const { return data[ind]; }
    Array operator+(Array<T> &a) {
        Array<T> ret(__size + a.__size);
        for (int i = 0; i < __size; i++) {
            ret[i] = data[i];
        }
        for (int i = __size; i < ret.__size; i++) {
            ret[i] = a[i];
        }
        return ret;
    }
    ~Array() { cout << "destructor" << endl; }
private:
    T __size, *data;
};

int main() {
    Array<int> a, b;
    Array<int> c = a + b;
    Array<int> d(forward<Array<int> &&>(a)); // 逻辑上a对象不再使用，所以这里使用移动构造会比较快

    return 0;
}

ENDS(test3)

int main() {
//    test1::main();
//    test2::main();
    test3::main();

    return 0;
}